home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
pascal
/
tpa22.zip
/
TPA_INTR.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1989-07-22
|
5KB
|
150 lines
{═══════════════════════════ INTERNAL.PAS ═══════════════════════════}
{ Demonstrates the use of an Internal statement in a Program. }
{ }
{ Internal and External statements require that you code an entire }
{ Procedure or Function in assembly, and that you explicitly code }
{ any necessary entry and exit code. For that reason it is usually }
{ more convenient to use Assemble or Asm statements, which can be }
{ mixed with Pascal statements on a line by line basis. On the }
{ other hand, Internal and External are useful when you want to }
{ completely eliminate the standard Pascal entry and exit code. In }
{ the Concat example below, the compiler would normally reserve 256 }
{ bytes on the stack and make a local copy of the String Value }
{ parameter S2. Since this parameter will not be modified, there is }
{ no reason to reserve limited stack space and make the local copy. }
{ Using Internal eliminates this unwanted entry code. }
{═══════════════════════════ INTERNAL.PAS ═══════════════════════════}
{ No Link directive - Internal Procedures and Functions are linked }
{ on a Proc by Proc basis by the Turbo Smart-Linker, resulting in }
{ a smaller EXE file. (External code is linked "all or nothing"). }
VAR
HexDigits: ARRAY[0..15] OF CHAR;
Str1: String;
FUNCTION HexByte(SourceByte: BYTE): INTEGER; Forward;
PROCEDURE Concat(Var S1; S2: String; Size1: INTEGER); Forward;
{- In a PROGRAM, Use FORWARD in place of EXTERNAL -}
Internal Example;
DATA SEGMENT WORD PUBLIC
EXTRN HexDigits:BYTE ;Not required by INTERNAL
DATA ENDS
CODE SEGMENT BYTE PUBLIC
ASSUME CS:CODE,DS:DATA ;Not required by INTERNAL
PUBLIC HexByte,Concat ;Not required by INTERNAL
; FUNCTION HexByte(SourceByte: BYTE): INTEGER; Forward;
HexByte PROC NEAR
MOV BX,SP
MOV AL,SS:[BX+2] ; Get parameter
Xor Ah,Ah ; set Ah = 0 to prevent Divide Overflow
Mov Bl,010
Div Bl ; Al = Quo, Ah = Rem
Mov Bx,Offset HexDigits
Xchg Al,Ah
XlatB
Xchg Al,Ah
XlatB ; Leave result in Ax
Ret 2
HexByte ENDP
; PROCEDURE Concat(Var S1; S2: String; Size1: INTEGER); Forward;
; Note: the String Value parameter S2 will Not be copied into a
; local work area. It will frequently represent a String Constant
; stored in the Code Segment in a space much smaller than 256 bytes.
; Because of this, and because of the compiler's automatic merging
; of string constants, it should not be modified.
String1 EQU DWORD PTR [BP+10]
String2 EQU DWORD PTR [BP+6]
SizeOf1 EQU WORD PTR [BP+4]
Concat PROC NEAR
Push Bp
Mov Bp,Sp
Push Ds
Cld ;set forward
Xor Ax,Ax
Mov Cx,SizeOf1
Dec Cx ;Max length is Allocated size - 1
Xor Ch,Ch ;In no case let str1 exceed 255
Les Di,String1
Lds Si,String2
Lodsb ;length(S2)
Add Al,Es:[Di] ;+Length(S1)
jC L1 ;exceeds 255, use Limit
Cmp Al,Cl
jA L1 ;exceeds Limit (use Limit)
Mov Cl,Al ;else use sum of lengths
Jmp Short L2
L1: Mov Al,Cl
L2: Sub Cl,Es:[Di] ;New length - old length(S1)
jBE Done ;New < Old, don't shorten
Xchg Al,Es:[Di] ;Put in new length, get old
Inc Di ;skip length byte
Add Di,Ax ;and original string to set dest
Rep Movsb ;Concatenate
Done: Pop Ds
Pop Bp
Ret 10
Concat ENDP
CODE ENDS
END (Internal Example)
CONST Result: RECORD
Len: BYTE;
Wrd: INTEGER;
END = (Len:2;Wrd:0);
VAR
n: BYTE;
ResultString: STRING[2] Absolute Result;
BEGIN {Main Program}
{- Demonstrate HexByte -}
HexDigits:= '0123456789ABCDEF';
FOR n := 0 TO 255 DO BEGIN
WRITE(n:3,' ');
Result.Wrd := HexByte(n);
WRITE(ResultString,' ');
END; {FOR n := 0 TO 255 DO }
WRITELN;
{- Demonstrate Concat -}
Str1 := 'String1';
WRITELN('Before Concat: ',Str1);
FOR n := 1 TO 5 DO BEGIN
Concat(Str1,'String2',SizeOf(Str1));
WRITELN('After Concat',n,': ',Str1);
END; {FOR n := 1 TO 5 DO }
Concat(Str1,'XXXXXXXXXXXX',45);
WRITELN('Partial Concat: ',Str1);
WRITELN(#13#10'Press a key to exit'#13#10);
Asm Mov Ah,0; {- Read from Keyboard -}
Asm Int 16h;
END. {Main}